package database;
import java.io.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Properties;
import java.util.Vector;

public class MyIMDB {



	private Properties props;
	private String useSQL="no";
	private File file;
	private FileInputStream fileIn;
	private FileOutputStream fileOut;
	private ObjectOutputStream objOut;
	private ObjectInputStream objIn;
	private boolean sql = false;
	private HashMap<String,user> user;
	private HashMap<String,group> group;
	private final String filename = "IM.data";


	public MyIMDB(){
		props = new Properties();
		file = new File("DB.cfg");
		if(!file.exists()){
			try{
				file.createNewFile();
			}
			catch(IOException e){
				e.printStackTrace();
			}
		}
		try{
			FileInputStream fileIn=new FileInputStream(file);
			if(fileIn.available()>0){
				props.load(new FileInputStream(file));
				useSQL=props.getProperty("useSQL");
				if(useSQL.equals("yes")){
					sql=true;
				}
				else{
					sql = false;
				}

			}
			else{
				BufferedWriter buf = new BufferedWriter(new FileWriter(file));
				props.put("useSQL", "no");
				buf.write("useDB=no\nuseSQL=no");
				buf.close();
				useSQL="no";
				sql=false;
			}
		}
		catch(IOException e){
			e.printStackTrace();
		}
		if(sql){

		}
		else{

			readFileToTable(filename);

		}



	}


	/**
	 * read datebase from the file
	 * @param fileName the filename of the datebase
	 */
	@SuppressWarnings("unchecked")
	private void readFileToTable(String fileName){
		file = new File(filename);
		if(!file.exists()){
			try{
				file.createNewFile();
			}
			catch(IOException e){
				e.printStackTrace();
			}
		}
		try{
			fileIn=new FileInputStream(file);
			if(fileIn.available()>0){
				objIn=new ObjectInputStream(fileIn);
				user=(HashMap<String, user>) ((HashMap<String, user>)objIn.readObject()).clone();
				group =(HashMap<String, group>) ((HashMap<String, group>)objIn.readObject()).clone();
				objIn.close();
			}
			else{
				user = new HashMap<String,user>();
				group = new HashMap<String,group>();
			}
			fileIn.close();
		}
		catch(IOException e){
			e.printStackTrace();
		}
		catch(ClassNotFoundException e){
			e.printStackTrace();
		}
	}

	/**
	 * save the database into the file
	 */
	public void saveDate(){
		file = new File(filename);
		try{
			fileOut = new FileOutputStream(file);
			objOut = new ObjectOutputStream(fileOut);
			objOut.writeObject(user);
			objOut.writeObject(group);
			objOut.close();
		}
		catch(IOException e){
			e.printStackTrace();
		}

	}


	//----------------------------------------------------------user--------------------------------//

	
	/**
	 * the login operation 
	 * @param name the username
	 * @param pwd the password
	 * 
	 * return true if the information is valid
	 */
	public boolean login(String name, String pwd){
		if(!sql){
			if(user.containsKey(name)==false){
				return false;
			}
			else if(user.get(name).getPwd().equals(pwd)){
				return true;
			}
			return false;
		}
		else{
			return false;
		}

	}
	/**
	 * create account operation
	 * @param name the username
	 * @param pwd the password
	 * @return true if successful created account
	 */
	public boolean addUser(String name, String pwd){
		if(!sql){
			if(user.get(name)==null){
				user.put(name, new user(name,pwd));
				return true;
			}
			else{
				return false;
			}
		}
		else{
			return false;
		}
	}
	/**
	 * the change password operation(not used)
	 * @param name account name
	 * @param oldPwd old password
	 * @param newPwd new password
	 * @return true if successful
	 */
	public boolean changePwd(String name, String oldPwd, String newPwd){
		if(!sql){
			user result = user.get(name);
			if(result==null){
				return false;
			}
			else if(result.getPwd().equals(oldPwd)){
				user.put(name, new user(name,newPwd));
				return true;
			}
			else{
				return false;
			}
		}
		else{
			return false;
		}
	}
	/**
	 * get friend list operation
	 * @param name the user name
	 * @return a string vector that contains the friend list
	 */
	public Vector<String> getFriendList(String name){
		if(!sql){
			user result = user.get(name);
			if(result == null){
				return null;
			}
			else{
				return result.getFriendList();
			}
		}
		else{
			return null;
		}
	}
	/**
	 * get message operation
	 * @param name the user name
	 * @return a message object vector
	 */
	public Vector<message> getMessage(String name){
		if(!sql){
			user result = user.get(name);
			if(result == null){
				return null;
			}
			else{
				return result.getMessage();

			}
		}
		else{
			return null;
		}
	}

	/**
	 * remove message operation (after sending, message needs to be removed)
	 * @param name account name
	 */
	public void removeMessages(String name){
		if(!sql){
			user result = user.get(name);
			if(result == null){
				return;
			}
			else{
				result.clearMessage();
				return;

			}
		}
		else{
			return;
		}
	}

	/**
	 * 
	 * @param owner the owner's name
	 * @param friend the name to add
	 * @return  on name already exist, return -1 on error, return 0; on success, 
	  return 1;
	 */
	public int addFriend(String owner, String friend){
		if(!sql){
			user result = user.get(owner);
			user f = user.get(friend);
			if(result == null||f==null){
				return 0;
			}
			else{
				f.addFriend(owner);
				return result.addFriend(friend);

			}
		}
		else{
			return 0;
		}
	}
	/**
	 * remove friend operation (not used)
	 * @param owner the friend list's owner
	 * @param friend the friend to remove
	 * @return 1 if success, 0 if fail
	 */
	public int removeFriend(String owner, String friend){
		if(!sql){
			user result = user.get(owner);
			if(result == null){
				return 0;
			}
			else{
				return result.removeFriend(friend);

			}
		}
		else{
			return 0;
		}
	}
	/**
	 * leave message operation (when someone sends the message)
	 * @param from the sender of the message
	 * @param to the reviver of the message
	 * @param message the text of the message
	 * @return true if success
	 */
	public boolean leaveMessage(String from, String to, String message){
		if(!sql){
			user result = user.get(to);
			if(result == null){
				return false;
			}
			else{
				result.addMessage(from, message);
				return true;

			}
		}
		else{
			return false;
		}
	}


	//-------------------------------------------group-------------------------------------------------------------//	
	/**
	 * create group operation
	 * @param the first member of the group
	 * @param groupName the name of the group
	 * @return true if success
	 */
	public boolean createGroup(String owner,String groupName){
		group got = group.get(groupName);
		if(got==null){
			group.put(groupName, new group(groupName,owner));
			return true;
		}
		else{
			got.addMember(owner);
			return true;
		}
	}
	/**
	 * add member into the group
	 * @param inviter the inviter
	 * @param invitee the member to add
	 * @param groupName the group's name
	 * @return true if success
	 */
	public boolean addIntoGroup(String inviter,String invitee,String groupName){
		group got = group.get(groupName);
		if(got == null){
			return false;
		}
		else{
			if(got.getPriviledge(inviter)>=0&&got.getPriviledge(inviter)<=2){
				got.addMember(invitee);
				return true;
			}
			else{
				return false;
			}
		}
	}
	/**
	 * leave group (not used)
	 * @param name the name of the the member to leave
	 * @param groupName the group name
	 */
	public void leaveGroup(String name,String groupName){

		group got = group.get(groupName);
		if(got != null)
			got.removeMember(name);
	}
	/**
	 * remove a member from the group (not used)
	 * @param owner the group owner
	 * @param name the name of the member to remove
	 * @param groupName the group name
	 * @return true if success
	 */
	public boolean kickMem(String owner, String name, String groupName){
		group got = group.get(groupName);
		if(got != null){
			if(got.getPriviledge(owner)==0){
				got.removeMember(name);
				return true;
			}
		}
		return false;
	}
	/**
	 * get group meessage
	 * @param name the user's name
	 * @return the vector contains user's group message
	 */
	public Vector<message> getGroupMessage(String name){
		if(!sql){
			user result = user.get(name);
			if(result == null){
				return null;
			}
			else{
				return result.getGroupMessage();

			}
		}
		else{
			return null;
		}
	}
	/**
	 * clear someone's group message
	 * @param name the user's name
	 */
	public void removeGroupMessages(String name){
		if(!sql){
			user result = user.get(name);
			if(result == null){
				return;
			}
			else{
				result.clearGroupMessage();
				return;

			}
		}
		else{
			return;
		}
	}


	/**
	 * send a group message into a group
	 * @param from the sender
	 * @param to the group name
	 * @param messag the text
	 */
	public void leaveGroupMessage(String from, String to, String messag){
		String message = from+" says:\n"+ messag;
		if(!sql){
			group result = group.get(to);
			if(result == null){
				System.out.println("group"+to+"not exist");
				return;
			}
			else{
				System.out.println("group "+to+" has "+result.mem.size()+" members");
				for(int i = 0;i< result.mem.size();i++){
					user got = user.get(result.mem.elementAt(i).name);
					if(got!=null){
						System.out.println("user "+result.mem.elementAt(i).name+" exist");
						got.addGroupMessage(to, message);
						System.out.println(result.mem.elementAt(i).name+" has "+got.getGroupMessage().size()+ " group messages");
					}
					else{
						System.out.println("user "+result.mem.elementAt(i).name+" does not exist");
					}
				}
				return;

			}
		}
	}

	/**
	 * get someone's group name list
	 * @param name the user's name
	 * @return the list of the group name
	 */
	public Vector<String> getGroup(String name){
		if(!sql){
			Vector<String> tmp = new Vector<String>();
			Collection<group> aaa = group.values();
			for(group a:aaa){
				Vector<String> aa = a.getMembers();
				for(int i = 0; i < aa.size();i++){
					if(aa.elementAt(i).equals(name)){
						tmp.add(a.name);
					}
				}
			}

			return tmp;

		}
		return null;
	}


}
